#include <ctime>
#include <cstdint>
#include <stdexcept>
#include <iostream>

//生成唯一ID
class Snowflake 
{
public:
    Snowflake(uint64_t worker_id)
        : worker_id_(worker_id), sequence_(0), last_timestamp_(0) {}

    //生成id
    uint64_t generate();

private:
    uint64_t worker_id_;
    uint64_t sequence_;
    uint64_t last_timestamp_;

    static constexpr uint64_t START_TIMESTAMP = 1577836800000; // 2020-01-01 00:00:00
    static constexpr uint64_t WORKER_ID_BITS = 10;
    static constexpr uint64_t SEQUENCE_BITS = 12;

    static constexpr uint64_t WORKER_ID_SHIFT = SEQUENCE_BITS;
    static constexpr uint64_t TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;

    inline uint64_t get_current_timestamp() { return static_cast<uint64_t>(std::time(nullptr)) * 1000; }
};

uint64_t Snowflake::generate()
{
    uint64_t timestamp = get_current_timestamp();
    if (timestamp < last_timestamp_) 
    {
        throw std::runtime_error("Clock moved backwards. Refusing to generate id.");
    }

    if (timestamp == last_timestamp_) 
    {
        sequence_ = (sequence_ + 1) & 0xFFF;    //是否超出12bit
        if (0 == sequence_) timestamp = get_current_timestamp();
    }
    else   sequence_ = 0;

    last_timestamp_ = timestamp;
    //1bit 41bit 10bit 12bit
    return ((timestamp - START_TIMESTAMP) << TIMESTAMP_LEFT_SHIFT) | (worker_id_ << WORKER_ID_SHIFT) | sequence_;
}

////简单测试用
// int main()
// {
//     Snowflake s(1);

//     //
//     std::cout << s.generate() << std::endl;
//     return 0;
// }